/* 
目标：为什么需要深拷贝。
  1. shouldComponentUpdate 生命周期函数内部需要比较新旧两个 list 数据
  2. 如果只是简单的解构赋值操作， 只是引用了 state.list 的内存地址。
  3. 内存地址相同，数据就比较不出来新旧，所以需要深拷贝生成新的对象内存地址。
  4. 这部分有点绕，可结合老师画的内存图去理解。

  Web项目：JS 中的数据的操作其实不占什么内存。
    DOM 操作 - DOM元素的增删改查。
    所以列表渲染一定要设置合适的 key 值。
*/
import React from 'react';

// List 子组件
class List extends React.Component {
  // shouldComponentUpdate 第一个参数，就是新的 props 数据
  shouldComponentUpdate(nextProps) {

    console.log('shouldComponentUpdate 是否更新？');
    console.log('新的 props', nextProps.list);
    console.log('旧的 props', this.props.list);
    // 最终只需要一行代码即可实现。比较新旧数组不一样的时候才更新 List 组件。
    return nextProps.list.toString() !== this.props.list.toString();
  }
  render() {
    console.log('List render 更新');
    return (
      <ol>
        {
          this.props.list.map((item, index) => <li onDoubleClick={() => this.props.aa(index)} key={item}>{item}</li>)
        }
      </ol>
    );
  }
}

class App extends React.Component {
  state = {
    inputValue: '菠萝',
    list: ['新闻1', '新闻2']
  };
  handleChange = (e) => {
    // console.log(e.target.value);
    this.setState({ inputValue: e.target.value });
  };

  handleClick = () => {
    let { inputValue, list } = this.state;

    // 真正的深拷贝两种解决方案：
    //    1. 函数递归 - 上网找就好
    //    2. JSON.parse(JSON.stringify(xxx)) 
    let newList = JSON.parse(JSON.stringify(list));

    if (inputValue.trim() === '') {
      alert('请输入内容');
      return;
    }
    if (newList.indexOf(inputValue) === -1) {
      newList.unshift(inputValue);
      this.setState({ list: newList, inputValue: '' });
    }
  };

  itemDelete = (index) => {
    // const { list } = this.state;
    // 把 list 构建成了一个新的地址。
    // 局部的 newList 和 this.state.list 地址就不同了。
    // [...数据] 不是真正的深拷贝。
    const newList = [...this.state.list];
    newList.splice(index, 1);
    this.setState({ list: newList });
  };
  render() {
    // 利用解构赋值获取数据
    const { list, inputValue } = this.state;
    return (
      <div className="App">
        <input type="text" value={inputValue} onChange={this.handleChange} />
        <button onClick={this.handleClick}>发布</button>
        {/* 这边传递给 子组件的其实就是  this.state.list 的内存地址而已 */}
        <List list={list} aa={this.itemDelete}></List>
      </div>
    );
  }
}


export default App;
